/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.metasploit.framework;

import org.metasploit.simple.Console;

import org.jruby.RubyNil;
import org.jruby.RubyHash;
import org.jruby.RubyString;
import org.jruby.RubyObject;
import org.jruby.RubyException;
import org.jruby.RubyNoMethodError;
import org.jruby.RubyClass;

import java.util.Map;

/**
 *
 * @author hughneale
 */
public class Exploits extends ModuleManager {

    //private Framework framework;
    //RubyHash exploits;
    //Ruby ruby;

    public Exploits(Framework f) {
        super(f, "exploits");
    }

    public String get_hash_val(String mod) {

        if (!this.self().keySet().contains(mod)) {
            Console.err("Exploit \"" + mod + "\" is not in the database.");
            return null;
        }

        Console.out("Exploit " + mod);

        RubyString exploit_name = RubyString.newString(this.getFramework().ruby(), mod);

        RubyClass cls = (RubyClass) this.getFramework().invoke(this.self(), "get_hash_val", exploit_name);

        String ob = ((RubyString) this.getFramework().invoke(cls, "name")).asJavaString();

        System.out.println("HASH:: dd " + ob);



        return "";
    }

    public Exploit create(String mod) {

        if (!this.self().keySet().contains(mod)) {
            Console.err("Exploit \"" + mod + "\" is not in the database.");
            return null;
        }

        Console.out("Exploit " + mod);

        RubyString exploit_name = RubyString.newString(this.getFramework().ruby(), mod);

        return new Exploit(this.getFramework(), (RubyObject) this.getFramework().invoke(this.self(), "create", exploit_name));

        //return new ;

    }

    public Session create(Exploit exp, Payload pay) {

        RubyString payload_name = RubyString.newString(this.getFramework().ruby(), pay.RefName());
        RubyHash map = RubyHash.newHash(this.getFramework().ruby());

        Map opts = exp.getOptions().get();

        if(opts == null) {
            Console.err("Not options defined.");
            return null;
        }
        
        map.putAll(opts);

        RubyHash exploit_options = map;

        RubyHash send = RubyHash.newHash(this.getFramework().ruby());

        send.put("Payload", payload_name);
        send.put("Options", exploit_options);
        //send.put("OptionStr", "RHOST=10.0.0.1,RPORT=21");
        send.put("LocalInput", (RubyObject) this.getFramework().scriptlet("Rex::Ui::Text::Input::Stdio.new"));
        send.put("LocalOutput", (RubyObject) this.getFramework().scriptlet("Rex::Ui::Text::Output::Stdio.new"));
        //send.put("RunAsJob", RubyBoolean.createTrueClass(this.ruby));
        //send.put("Quiet", RubyBoolean.createFalseClass(quick));
        return create_simple(exp, send);
    }

    public Session create(Exploit exp, Options opt) {

        RubyHash send = RubyHash.newHash(this.getFramework().ruby());
        send.putAll(opt.get());

        return create_simple(exp, send);

    }

    private Session create_simple(Exploit exp, RubyObject... opts) {

        Object oretu = this.getFramework().invoke(exp.self(), "exploit_simple", opts);

        //Console.pls("\t\tClass Returned " + oretu.getClass().getCanonicalName());

        if (oretu instanceof RubyNil) {
            // RubyNil got nothing :(
            Console.err("Exploit failed.");
            this.error(exp.self());
            return null;
        } else if (oretu instanceof RubyNoMethodError) {
            Console.err("JRuby Failed due to method exception.");
            Console.err(((RubyNoMethodError) oretu).toString());
            return null;
        } else if (oretu instanceof RubyException) {
            Console.err("JRuby Failed due to Ruby Exception.");
            this.getFramework().exception((RubyObject) oretu);
            return null;
        } else {
            Console.pls("Exploit Succeeded. " + oretu.getClass().getCanonicalName());
            return new Session(this.getFramework(), (RubyObject) oretu);
        }
    }
 
}
